package cn.bytepulse.exception;


import cn.bytepulse.constant.HttpStatus;
import cn.bytepulse.pojo.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * 统一异常处理器
 *
 * @author jiejiebiezheyang
 * @since 2023-04-03 15:40
 */
@Slf4j
@Order(-999)
@ControllerAdvice
public class ExceptionProcessor {

    /**
     * 数据校验异常
     */
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public AjaxResult resolveException(MethodArgumentNotValidException ex) {
        log.error("数据校验异常", ex);
        List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
        Set<String> msg = new HashSet<>();
        for (ObjectError error : allErrors) {
            msg.add(error.getDefaultMessage());
        }
        return AjaxResult.error("数据校验失败", msg);
    }

    /**
     * sql 错误
     */
    @ResponseBody
    @ExceptionHandler(DataAccessException.class)
    public AjaxResult resolveException(DataAccessException ex) {
        log.error("sql执行异常", ex);
        String message = Objects.requireNonNull(ex.getRootCause()).getMessage();
        return AjaxResult.error(message);
    }

    /**
     * sql 错误
     */
    @ResponseBody
    @ExceptionHandler(SQLException.class)
    public AjaxResult resolveException(SQLException ex) {
        log.error("sql执行异常", ex);
        return AjaxResult.error("数据校验失败", ex);
    }

    /**
     * 授权异常
     */
    @ResponseBody
    @ExceptionHandler(AccessDeniedException.class)
    public AjaxResult resolveException(AccessDeniedException ex) {
        log.error("授权异常", ex);
        return AjaxResult.error(HttpStatus.FORBIDDEN, ex.getMessage());
    }

    /**
     * 未授权异常
     */
    @ResponseBody
    @ExceptionHandler(BadCredentialsException.class)
    public AjaxResult resolveException(BadCredentialsException ex) {
        log.error("未授权异常", ex);
        return AjaxResult.error(HttpStatus.UNAUTHORIZED, ex.getMessage());
    }

    /**
     * 统一异常处理方法
     * 将异常进行统一处理,并将结果返回给前端
     */
    @ResponseBody
    @ExceptionHandler()
    public AjaxResult resolveException(Exception ex) {
        log.error("Controller全局异常捕获", ex);
        return AjaxResult.error(ex.getMessage());
    }
}
